package com.jie.component.bloomfilter.core;


import com.jie.common.util.SpringUtil;
import com.jie.component.exception.base.FrameException;
import com.jie.component.exception.enums.FrameError;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;

import java.util.HashMap;
import java.util.Map;

/**
 * @author jie
 * @version 1.0 2025-02-11
 */
@Slf4j
public class BloomFilterManager {
    private final RedissonClient redissonClient;

    private final Map<String, RBloomFilter<String>> bloomFilterMap;

    public BloomFilterManager(RedissonClient redissonClient) {
        this.bloomFilterMap = new HashMap<>();
        this.redissonClient = redissonClient;
    }

    public boolean addBloomFilter(String name, long expectedInsertions, double falseProbability) {
        boolean b = bloomFilterMap.containsKey(name);
        if (b) {
            log.warn("重复添加布隆过滤器 {}", name);
            return false;
        }
        RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(SpringUtil.getPrefixDistinctionName() + "-" + name);
        b = bloomFilter.tryInit(expectedInsertions, falseProbability);
        if (!b) {
            log.error("初始化布隆过滤器失败 {}", name);
            throw new FrameException(FrameError.INIT_BLOOM_FILTER_ERROR);
        }

        bloomFilterMap.put(name, bloomFilter);
        return true;
    }

    private RBloomFilter<String> getBloomFilter(String name) {
        RBloomFilter<String> bloomFilter = bloomFilterMap.getOrDefault(name, null);
        if (bloomFilter == null) {
            log.warn("布隆过滤器不存在 {}", name);
            throw new FrameException(FrameError.BLOOM_FILTER_NOT_EXIST);
        }
        return bloomFilter;
    }

    public boolean add(String name, String data) {
        RBloomFilter<String> cachePenetrationBloomFilter = getBloomFilter(name);
        return cachePenetrationBloomFilter.add(data);
    }

    public boolean contains(String name, String data) {
        RBloomFilter<String> cachePenetrationBloomFilter = getBloomFilter(name);
        return cachePenetrationBloomFilter.contains(data);
    }

    public long getExpectedInsertions(String name) {
        RBloomFilter<String> cachePenetrationBloomFilter = getBloomFilter(name);
        return cachePenetrationBloomFilter.getExpectedInsertions();
    }

    public double getFalseProbability(String name) {
        RBloomFilter<String> cachePenetrationBloomFilter = getBloomFilter(name);
        return cachePenetrationBloomFilter.getFalseProbability();
    }

    public long getSize(String name) {
        RBloomFilter<String> cachePenetrationBloomFilter = getBloomFilter(name);
        return cachePenetrationBloomFilter.getSize();
    }

    public int getHashIterations(String name) {
        RBloomFilter<String> cachePenetrationBloomFilter = getBloomFilter(name);
        return cachePenetrationBloomFilter.getHashIterations();
    }

    public long count(String name) {
        RBloomFilter<String> cachePenetrationBloomFilter = getBloomFilter(name);
        return cachePenetrationBloomFilter.count();
    }
}
